package space.edge.d.demo.qrcode.codescanner.scanner;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import space.edge.d.demo.qrcode.common.Result;
import space.edge.d.demo.qrcode.codescanner.camera.CameraManager;

import java.io.IOException;

/**
 * Created by gsl on 2017/10/26.
 * 继承自SurfaceView
 */

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    public static final int STATE_RESUMED = 0x01;
    public static final int STATE_STOPPED = 0x00;

    private CameraManager cameraManager;

    private boolean surfaceAlive;
    private int cameraId = Integer.MIN_VALUE;

    private PreviewHandler previewHandler;
    private ScannerCallback scannerCallback;
    private int state = STATE_STOPPED;

    public CameraPreview(Context context) {
        super(context);
        init(context);
    }

    public CameraPreview(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        cameraManager = new CameraManager(context);
        getHolder().addCallback(this);
    }

    public void resume() {
        state = STATE_RESUMED;
        if (cameraId == Integer.MIN_VALUE) {
            int cameraId = PreviewUtil.findAppropriateCameraId(this.getContext().getApplicationContext(), true);
            if (cameraId == Integer.MIN_VALUE)
                throw new IllegalStateException("cameraId not found");
            this.cameraId = cameraId;
        }
        startPreviewAndDecode();
    }

    public void setFramingRect(Rect rect) {
        if (cameraManager == null)
            return;
        cameraManager.setManualFramingRect(rect.width(), rect.height(), rect.top);
    }

    public void pause() {
        state = STATE_STOPPED;
        if (previewHandler != null) {
            previewHandler.quit();
            previewHandler = null;
        }
        if (cameraManager != null)
            cameraManager.closeDriver();
        if (!surfaceAlive)
            getHolder().removeCallback(this);
    }

    public void setCallback(ScannerCallback callback) {
        scannerCallback = callback;
        if (previewHandler != null) {
            previewHandler.setCallback(callback);
        }
    }

    private void startPreviewAndDecode() {
        if (!surfaceAlive || (cameraId == Integer.MIN_VALUE))
            return;
        cameraManager.setManualCameraId(cameraId);
        initCamera(getHolder());
    }

    private void initCamera(SurfaceHolder holder) {
        if (surfaceAlive) {
            if (cameraManager.isOpen())
                return;
            try {
                cameraManager.openDriver(holder);
                cameraManager.startPreview();
                if (previewHandler == null) {
                    previewHandler = new PreviewHandler(cameraManager);
                    if (scannerCallback != null && scannerCallback != previewHandler.getCallback())
                        previewHandler.setCallback(scannerCallback);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public int getState() {
        return state;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (holder == null) {
            // TODO: 2017/10/27  holder 为空异常
            return;
        }
        surfaceAlive = true;
        startPreviewAndDecode();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        surfaceAlive = false;
        if (cameraManager != null)
            cameraManager.stopPreview();
    }

    public interface ScannerCallback {
        void onSuccess(Result result);

        void onFail();
    }

}
